#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h> //引入相应库
#include <EEPROM.h>

#include <MQTT.h>

const char* mqtt_server = "mq.tongxinmao.com";//服务器的地址 
const int mqtt_port=18830;//服务器端口号
String m_ChipId;
long lastMsg = 0;  
const byte DNS_PORT = 53; //DNS服务端口号，一般为53
const char* apPassword = "11111111";

IPAddress apIP(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);

struct wifiparams
{
  int isAPMode;
  char ssid[64];
  char password[64];
};

wifiparams pwifiparams;
int pwificonnectcount;
WiFiClient espClient;
MQTTClient mqttclient;
DNSServer dnsserver; //声明DNSServer对象
ESP8266WebServer server(80);

void handleRoot() {
  server.send(400, "text/html", "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'/><title>wifi配置</title></head><body><div align='center'><div style='height:100px;'></div><dir>wifi配置</dir><form action='/config/' method='post' enctype='text/plain'><table border='0' cellspacing='10'><tr><td>wifi名称：<input name='ssid' type='text' style='border:1;'/></td></tr><tr><td>wifi密码：<input name='password' type='password' style='border:1;'/></td></tr></table><button type='submit'>提交</button></form></div></body></html>");
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

void handleconfig() {
  if(server.method() == HTTP_POST) {
    String tmpssid="";
    String tmpparams = "";
    String tmppassword="password=hello";

    tmpparams = server.arg(0);
   // tmppassword = server.arg(1);

    int pcount = 0;
    int pssidpos = 0;
   for(int i=0;i<tmpparams.length();i++) {
    if(tmpparams.charAt(i) == '\n') {
      if(pcount == 0) {
        tmpssid=tmpparams.substring(0,i);
        pssidpos=i+1;
      }
      else if(pcount == 1) {
        tmppassword=tmpparams.substring(pssidpos,i);
        break;
      }
      pcount += 1;
    }
   }

    uint8_t tmpssidlength = tmpssid.length();
    uint8_t tmppasswordlength = tmppassword.length();

    Serial.println(tmpssidlength);  
    Serial.println(tmppasswordlength);      

    if(tmpssidlength > 0) {
      tmpssid = tmpssid.substring(5);
    }

    if(tmppasswordlength > 0) {
      tmppassword = tmppassword.substring(9);
    }          

    Serial.println("get data2:");
    Serial.println(tmpssid);
    Serial.println(tmppassword);  

    tmpssidlength = tmpssid.length();
    tmppasswordlength = tmppassword.length();

    Serial.println(tmpssidlength);  
    Serial.println(tmppasswordlength);  

    if((tmpssidlength <= 0 || tmpssidlength >= 64) || 
       (tmppasswordlength <= 0 || tmppasswordlength >= 64)) {
        server.send(400,"text/html","<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'/><title>wifi配置</title></head><body><div align='center'><div style='height:100px;'></div><dir>wifi名或者密码不能为空，也不能大于64个字符，请重新填写.</dir><div><a href='#' onClick='javascript:history.back(-1);'>返回上一页</a></div></body></html>");
        return;
    }  

    server.send(400,"text/html","<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'/><title>wifi配置</title></head><body><div align='center'><div style='height:100px;'></div><dir>wifi配置成功.</dir></body></html>");
    delay(5000);    

    memset(&pwifiparams,0,sizeof(pwifiparams));

    pwifiparams.isAPMode=1;
    strcpy(pwifiparams.ssid,tmpssid.c_str());
    strcpy(pwifiparams.password,tmppassword.c_str());

    int fVar1Addr = 0;
    EEPROM.put( fVar1Addr, pwifiparams );
    EEPROM.commit();
    delay(5000);

    if(pwifiparams.isAPMode == 1) {
      //WiFi.mode(WIFI_STA);
      setup_wifi();//自动连WIFI接入网络
    }  
   }
}

void setup_wifi() {//自动连WIFI接入网络
  delay(10);
  //设置STA网络参数
  IPAddress sip(192, 168, 1, 29);//本地IP
  IPAddress sip1(192, 168, 1, 1);//本地网关
  IPAddress sip2(255, 255, 255, 0);//本地子网掩码
  String tmpssid = pwifiparams.ssid;
  String tmppassword = pwifiparams.password; 
  tmpssid = tmpssid.substring(0,tmpssid.length()-1);
  tmppassword = tmppassword.substring(0,tmppassword.length()-1);
  Serial.println(tmpssid.length());
  Serial.println(tmppassword.length());  
  
  WiFi.begin(tmpssid,tmppassword );
  //WiFi.config(sip,sip1,sip2);//设置本地网络参数
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("connectiong...");
    pwificonnectcount += 1;

    //如果连接30次都不成功的话，就退出，需要重新设置
    if(pwificonnectcount > 30) {
      pwifiparams.isAPMode=0;
      break;
    }
  }

  if(pwifiparams.isAPMode == 0) {
    Serial.println("disconnectied.");
  }
  else {
    Serial.println("connectied.");
  }
}

void messageReceived(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);

  mqttclient.publish(topic+"1",payload,false,2);
}

void reconnect() {//等待，直到连接上服务器
  while (!mqttclient.connected()) {//如果没有连接上
    if (mqttclient.connect("biloba")+random(999999999)) {//接入时的用户名，尽量取一个很不常用的用户名
      Serial.println("mqtt server connected.");
      mqttclient.subscribe("AKINGLED",2);//接收外来的数据时的intopic
      Serial.println("message LED subscribe success.");
    } else {
      Serial.println("connect mqtt server failed, rc=");//连接失败
      Serial.println(mqttclient.returnCode());//重新连接
      Serial.println(" try again connect mqtt server in 5 seconds");//延时5秒后重新连接
           
      delay(5000);
    }
  }
}

bool startAP(bool state) {
  if (state) {
    m_ChipId = (String)ESP.getChipId();
    String apName = ("ESP8266_"+m_ChipId);  // 2 设置WIFI名称
    const char *softAPName = apName.c_str();  

    Serial.println(WiFi.softAPConfig(apIP, gateway, subnet));
    Serial.println(WiFi.softAP(softAPName, apPassword));
    Serial.println(WiFi.softAPIP());
    Serial.println(WiFi.softAPmacAddress());

    return true;
  } else {
    //WiFi.mode(WIFI_STA);
    WiFi.softAPdisconnect(true);
    return false;
  }
}

void setup() {//初始化程序，只运行一遍
  pwificonnectcount=0;
  Serial.begin(115200);
  EEPROM.begin(sizeof(wifiparams));  
  WiFi.mode(WIFI_AP_STA);
  //pinMode(BUILTIN_LED, OUTPUT);  // initialize onboard LED as output
  delay(1000);
  
  memset(&pwifiparams,0,sizeof(pwifiparams));

  int fVar1Addr = 0;
  EEPROM.get( fVar1Addr, pwifiparams );  

  /*if(pwifiparams.isAPMode==0){
    Serial.println("pwifiparams.isAPMode is running?????");
    pwifiparams.isAPMode=1;
    strcpy(pwifiparams.ssid,"akinggw ");
    strcpy(pwifiparams.password,"akinggw12 ");
  }*/

  Serial.println(pwifiparams.isAPMode);
  Serial.println(pwifiparams.ssid);
  Serial.println(pwifiparams.password);

  //WiFi.mode(WIFI_AP);
  startAP(true); 
  delay(100);

  server.on("/", handleRoot);
  server.on("/config/",handleconfig);
  server.onNotFound(handle_NotFound);

  dnsserver.start(DNS_PORT, "config.io", apIP); //启动DNS服务,example.com即为注册的域名
  
  server.begin();
  Serial.println("HTTP server started");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());   

  mqttclient.begin(mqtt_server,mqtt_port, espClient);
  mqttclient.onMessage(messageReceived);  

  if(pwifiparams.isAPMode == 1) {
    //WiFi.mode(WIFI_STA);
    setup_wifi();//自动连WIFI接入网络
    delay(1000);
  }  
}

void loop() {//主循环
   dnsserver.processNextRequest(); //处理来自客户端的请求
   delay(10);
   server.handleClient();  
   delay(10);
   
   if(pwifiparams.isAPMode == 1) {
     if (!mqttclient.connected()) {
       reconnect();//确保连上服务器，否则一直等待。
     }
     else {
       mqttclient.loop();//MUC接收数据的主循环函数。
       delay(10);
  
       long now = millis();
       if (now - lastMsg > 5000) {
         lastMsg = now;
         String tmpStr = "{device:"+m_ChipId+",'status':'on'}";
         mqttclient.publish("home/status/",tmpStr.c_str() );
       }
     }
   }
}
